package org.example.fboot.config.jwt;

import com.alibaba.fastjson2.JSONObject;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.security.Keys;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.example.fboot.jwt.JwtUtils;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;

import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


/**
 * 用户组件
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AccessComponent {

    @Resource
    private final JwtConfig jwtConfig;
    @Resource
    private final ReactiveRedisTemplate<String, String> reactiveRedisTemplate;

    private String prefixKey(String key) {
        return "user:" + key;
    }

    public void out(String user) {
        reactiveRedisTemplate.expire(prefixKey(user), Duration.ZERO).block();
    }

    @PostConstruct
    public void init() {
        //初始化
        log.info("-------------------------初始化jwt配置前 key:{}-------------------------", JwtUtils.SECRET_KEY);
        log.info("-------------------------初始化jwt配置前 outTime:{}-------------------------", JwtUtils.TOKEN_EXPIRE_MILLIS);
        JwtUtils.SECRET_KEY = jwtConfig.key;
        JwtUtils.TOKEN_EXPIRE_MILLIS = jwtConfig.tokenOutTime;
        JwtUtils.KEY = Keys.hmacShaKeyFor(JwtUtils.SECRET_KEY.getBytes());
        log.info("-------------------------初始化jwt配置后 key:{}-------------------------", JwtUtils.SECRET_KEY);
        log.info("-------------------------初始化jwt配置后 outTime:{}-------------------------", JwtUtils.TOKEN_EXPIRE_MILLIS);
    }

    public Claims getPayload(String token)  {
        if (StringUtils.hasText(token)) {
            return JwtUtils.parseClaim(token).getPayload();
        }
        return null;
    }
    public String createToken(Authentication authentication) {
        return createToken(null,authentication);
    }
    public String createToken(ServerWebExchange exchange,Authentication authentication) {
        Map<String, Object> map = new HashMap<>();
        map.put(HttpHeaders.AUTHORIZATION, JSONObject.from(authentication));
        map.put("wsId", DigestUtils.md5DigestAsHex(authentication.getName().getBytes(StandardCharsets.UTF_8)));
        return createToken(exchange,authentication, map);
    }

    public String createToken(ServerWebExchange exchange,Authentication authentication, Map<String, Object> payload) {
        String accessToken = JwtUtils.getAccessToken(payload);
        reactiveRedisTemplate.opsForHash().put(prefixKey(authentication.getName()), "token", accessToken).block();
        //设置超时时间
        reactiveRedisTemplate.expire(prefixKey(authentication.getName()), Duration.ofSeconds(jwtConfig.tokenOutTime)).block();
        if (Objects.nonNull(exchange)) {
            ServerHttpResponse response = exchange.getResponse();
            response.getHeaders().add(HttpHeaders.AUTHORIZATION, accessToken);
            response.getHeaders().add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "Authorization");
        }
        return accessToken;
    }
}

